﻿#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.Serialization.Json;
using System.Text;

#endregion

namespace VinhSon.Intranet.Models.ExtJs
{
    public static class QueryableExtensions
    {
        private static T JsonDeserialize<T>(string jsonString)
        {
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof (T));
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
            T obj = (T) ser.ReadObject(ms);
            return obj;
        }

        public static IQueryable<T> OrderBy<T>(this IQueryable<T> query,
                                               string sortEx,
                                               Func<IQueryable<T>, IOrderedQueryable<T>> orderBy,
                                               IEnumerable<string> sort)
        {
            if(!string.IsNullOrEmpty(sortEx)
               && sort != null)
            {
                DataSorter sorter = JsonDeserialize<DataSorter>(string.Format("{{\"Items\":{0}}}",
                                                                              sortEx));
                IEnumerable<SortItem> q1 = sorter.Items.Join(sort,
                                                             c => c.property,
                                                             v => v,
                                                             (c,
                                                              v) => c);
                if(q1.Any())
                {
                    bool first = true;
                    foreach (SortItem item in q1)
                    {
                        query = query.OrderBy(item.property,
                                              item.direction,
                                              first);
                        first = false;
                    }
                    return query;
                }
            }
            return orderBy(query);
        }

        private static IQueryable<T> OrderBy<T>(this IQueryable<T> query,
                                                string sortColumn,
                                                string direction,
                                                bool first)
        {
            string methodName = string.Format("{0}{1}",
                                              first
                                                      ? "OrderBy"
                                                      : "ThenBy",
                                              ((direction + "").ToLower() == "desc")
                                                      ? "Descending"
                                                      : "");
            ParameterExpression expression = Expression.Parameter(query.ElementType,
                                                                  "p");
            MemberExpression body = null;
            foreach (string str2 in sortColumn.Split(new[] {'.'}))
            {
                body = body != null
                               ? Expression.Property(body,
                                                     str2)
                               : Expression.Property(expression,
                                                     str2);
            }
            LambdaExpression expression3 = Expression.Lambda(body,
                                                             new[] {expression});
            MethodCallExpression expression4 = Expression.Call(typeof (Queryable),
                                                               methodName,
                                                               new[] {query.ElementType, body.Type},
                                                               new[] {query.Expression, Expression.Quote(expression3)});
            return query.Provider.CreateQuery<T>(expression4);
        }

    }
}
